#pragma once

#include<iostream>
#include<string>
#include<cstring>
#include<cerrno>
#include<cstdlib>
#include<strings.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<functional>
#include"Thread.hpp"
#include"LockGuard.hpp"
#include"err.hpp"

namespace nt_client
{
    class Udpclient
    {
    public:
        Udpclient(std::string ip,uint16_t port)
        :_Serverip(ip),_Serverport(port)
        {
            _recv=new Thread(1,std::bind(&Udpclient::RecvMessage,this));
            _send=new Thread(2,std::bind(&Udpclient::SendMessage,this));
        }

        ~Udpclient()
        {
            _recv->join();
            _send->join();

            delete(_recv);
            delete(_send);
        }

        void StartClient()
        {
            //1.创建套接字
            _sock=socket(AF_INET,SOCK_DGRAM,0);

            if(_sock==-1)
            {
                std::cout<<"Create socket fail:"<<strerror(errno)<<std::endl;
                exit(SOCKET_ERR);
            }

            std::cout<<"Create socket success"<<_sock<<std::endl;

            //2.构建服务器端的sockaddr_in结构体信息
            bzero(&_serve,sizeof(_serve));
            _serve.sin_family=AF_INET;
            _serve.sin_addr.s_addr=inet_addr(_Serverip.c_str());
            _serve.sin_port=htons(_Serverport);

            //启动线程
            _recv->run();
            _send->run();

        }
         // 发送消息
        void RecvMessage() 
        {
            while(true)
            {
                // 发送消息
                std::string msg;
                std::cout << "Input Message# ";
                std::getline(std::cin, msg);

                ssize_t n = sendto(_sock, msg.c_str(), msg.size(), 0, (const struct sockaddr*)&_serve, sizeof(_serve));

                if(n == -1)
                {
                    std::cout << "Send Message Fail: " << strerror(errno) << std::endl;
                    continue; // 重新输入消息并发送
                }
            }
        }

        // 接收消息
        void SendMessage()
        {
            char buff[1024];
            while(true)
            {
                // 2.接收消息
                socklen_t len = sizeof(_serve); // 创建一个变量，因为接下来的参数需要传左值
                ssize_t n = recvfrom(_sock, buff, sizeof(buff) - 1, 0, (struct sockaddr*)&_serve, &len);

                if(n > 0)
                    buff[n] = '\0';
                else
                    continue;

                std::cout << "Client get message " << buff << std::endl;
            }
        }

    private:
        std::string _Serverip;
        uint16_t _Serverport;
        int _sock;
        struct sockaddr_in _serve;
        Thread* _recv;
        Thread* _send;
    };

    
}

